package com.mioto.ld.security.filter;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.mioto.ld.module.personal.model.User;
import com.mioto.ld.result.ResultData;
import com.mioto.ld.result.SystemTip;
import com.mioto.ld.security.config.JwtConfig;
import com.mioto.ld.utils.ResultUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * @author mioto-qinxj
 * @date 2024/4/11
 * @desc JWT接口请求校验拦截器 请求接口时会进入这里验证Token是否合法和过期
 */
@Slf4j
public class JwtAuthenticationTokenFilter extends BasicAuthenticationFilter {

    public JwtAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 获得TokenHeader
        String tokenHeader = request.getHeader(JwtConfig.tokenHeader);
        if (StrUtil.isNotEmpty(tokenHeader) && tokenHeader.startsWith(JwtConfig.tokenPrefix)) {
            try {
                // 获取请求头中JWT的Token
                if (!StrUtil.isEmpty(request.getHeader(JwtConfig.tokenHeader))) {
                    // 截取JWT前缀
                    String token = request.getHeader(JwtConfig.tokenHeader).replace(JwtConfig.tokenPrefix, "");
                    // 解析JWT
                    Claims claims = Jwts.parser().setSigningKey(JwtConfig.secret).parseClaimsJws(token).getBody();
                    // 获取用户名
                    String username = claims.getSubject();
                    String userId = claims.getId();
                    if (StrUtil.isNotEmpty(username) && StrUtil.isNotEmpty(userId)) {
                        String[] array = StrUtil.split(claims.get("authorities").toString(), ",");
                        Set<SimpleGrantedAuthority> grantedAuthorities = new HashSet<>(array.length);
                        User user = Convert.convert(User.class, claims.get("logonUser"));
                        for (int i = 0; i < array.length; i++) {
                            grantedAuthorities.add(new SimpleGrantedAuthority(array[i]));
                        }
                        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, StrUtil.EMPTY, grantedAuthorities);
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }else {
                       throw new Exception();
                    }
                }
            } catch (ExpiredJwtException e) {
                log.error("token expired");
                ResultUtil.responseJson(response, ResultData.result(SystemTip.TOKEN_EXPIRED));
                return;
            } catch (Exception e) {
                log.error("token verify");
                ResultUtil.responseJson(response, ResultData.result(SystemTip.TOKEN_VERIFY));
                return;
            }
        }
        chain.doFilter(request, response);
    }
}
